<?php
/**
 * Class loader for all XJConf classes.
 *
 * @package  XJConf
 * @version  $Id: XJConfLoader.php 146 2009-10-26 21:58:30Z mikey $
 */
/**
 * Class loader for all XJConf classes.
 *
 * The class loader takes care that all class files are only loaded once. It
 * allows all classes to include the required files without knowing where they
 * reside or if they have been loaded before.
 *
 * @package  XJConf
 */
class XJConfLoader
{
    /**
     * list of loaded files
     *
     * @var  array<String>
     */
    private static $loadedClasses = array();

    /**
     * method to load files from source path
     *
     * Usage: XJConfLoader::load('path::to::Classfile');
     * or load more than one at once:
     * XJConfLoader::load('path::to::first::Class',
                          'path::to::second::Class'
       );
     * You may name as many files as you like, there is no restriction
     * on the number of arguments.
     *
     * @param   string  list of file names to load
     */
    public static function load()
    {
        $classes = func_get_args();
        if (count($classes) == 0) {
            // its ok to call this without any arguments, this won't cause any harm
            return;
        }

        $realFiles = array();
        foreach ($classes as $className) {
            $nqClassName = self::getNonQualifiedClassName($className);
            if (in_array(str_replace('net::xjconf::', '', $className), self::$loadedClasses) === TRUE || class_exists($nqClassName, FALSE) === TRUE || interface_exists($nqClassName, FALSE) === TRUE) {
                continue; // step to next file if file is already loaded
            }

            $uri = null;
            array_push(self::$loadedClasses, str_replace('net::xjconf::', '', $className));
            if (class_exists('StarClassRegistry', false) === true) {
                if (substr($className, 0, 13) != 'net::xjconf::') {
                    $uri = StarClassRegistry::getUriForClass('net::xjconf::' . $className);
                } else {
                    $uri = StarClassRegistry::getUriForClass($className);
                }
            }
            if ($uri === null) {
                $uri = dirname(__FILE__) . '/' . self::mapClassname($className);
            }
            
            require $uri;
        }
    }

    /**
     * returns the non qualified class name from a full qualified class name
     *
     * @param   string  $fqClassName
     * @return  string
     */
    public static function getNonQualifiedClassName($fqClassName)
    {
        $classNameParts = explode('::', $fqClassName);
        return $classNameParts[count($classNameParts) - 1];
    }

    /**
     * checks whether a file with the given class exists
     *
     * @param   string  $fqClassName
     * @return  bool
     */
    public static function classFileExists($className)
    {
        if (class_exists('StarClassRegistry') == false) {
            return file_exists(dirname(__FILE__) . '/' . self::mapClassname($className));
        }

        if (substr($className, 0, 13) != 'net::xjconf::') {
            $fqClassName = 'net::xjconf::' . $className;
        } else {
            $fqClassName = $className;
        }
        
        if (StarClassRegistry::getFileForClass($fqClassName) != null) {
            return true;
        }
        if (substr(dirname(__FILE__), 0, 7) == 'star://') {
            return false;
        }
        
        return file_exists(dirname(__FILE__) . '/' . self::mapClassname($className));
    }

    /**
     * maps classnames given to loadClass() into required ones for load()
     *
     * @param  string  $classname  name of class given to loadClass()
     * @return string  name of class required for load()
     */
    private static function mapClassname($classname)
    {
        return str_replace('::', '/', $classname) . '.php';
    }
}
?>